<template>
  <div style="height: 100%; overflow: hidden">
    <el-table size="small" @selection-change="handleSelectionChange" :data="myTableData" highlight-current-row border
      style="width: 100%; overflow: hidden" :height="tableHeight ? tableHeight : 'calc(100% - 100px)'">

      <el-table-column align="center" v-if="tableColumn.select" type="selection" width="55">
      </el-table-column>

      <el-table-column v-else align="center" type="index" width="50"
        :fixed="tableColumn.column[1].fixed ? tableColumn.column[1].fixed : false"> </el-table-column>

      <el-table-column align="center" :min-width="item.minWidth ? item.minWidth : 150" v-if="item.isShow" sortable
        :prop="item.key" :label="item.label" v-for="(item, index) in tableColumn.column" :key="index"
        :fixed="item.fixed ? item.fixed : false">

        <template slot-scope="scope">
          <div v-if="item.type == 'date'">
            <span v-if="item.before" :style="item.before.style" @click="clickEvent(item.before, scope.row)">
              {{ item.before.text(scope.row) }}
            </span>
            {{ getScopeData(scope.row, item.key, item) | timestampToTime }}
            <span v-if="item.after" :style="item.after.style" @click="clickEvent(item.after, scope.row)">
              {{ item.after.text(scope.row) }}
            </span>
          </div>
          <div v-else-if="item.type == 'select'">
            <span v-for="(name, index) in mapName(item, getScopeData(scope.row, item.key, item))" :key="index">
              {{ name }}
            </span>
          </div>
          <div v-else-if="item.type == 'image'"
            style="width: 100%; height: 100%; display: flex; justify-content: center">
            <img :src="getScopeData(scope.row, item.key, item)" alt="" srcset="" width="75%" style="max-width: 85px;" />
          </div>

          <div v-else-if="item.type == 'tag'">
            <el-tag :key="item.label" :type="item.calc_tag_color(getScopeData(scope.row, item.key, item), scope.row)"
              :effect="item.effect">
              {{ getScopeData(scope.row, item.key, item) }}
            </el-tag>
            <div v-if="item.after" :style="item.after.style"
              @click="item.after.type == 'text' ? '' : clickEvent(item.after, scope.row)">
              {{ item.after.text(scope.row) }}
            </div>
          </div>

          <div v-else-if="item.type == 'row_many'" style="width: 100%; height: 100%; text-align: center; display: flex; text-align: center; justify-content: space-evenly;align-items: flex-start;
          ">

            <div v-if="item.calc_column && item.calc_column(getScopeData(scope.row, item.key, item), scope.row)">
              {{ item.calc_column(getScopeData(scope.row, item.key, item), scope.row) }}
            </div>

            <template v-else>

              <!-- <div v-for="(map_index, index) in Array.from({ length: item.calc_column?item.calc_column(getScopeData(scope.row, item.key, item)):item.column?item.column:1 }, (_, i) => i)" :key="index"> -->
              <div v-for="(map_index, index) in Array.from({ length: item.column ? item.column : 1 }, (_, i) => i)"
                :key="index">
                <div v-for="(dict, index) in get_row_many(map_index, item, getScopeData(scope.row, item.key, item))"
                  :key="index" :style="dict.style">
                  {{ dict.label }}:{{ dict.value }}
                </div>
              </div>
            </template>
          </div>


          <div v-else-if="item.type == 'percentage'"
            style="width: 100%; height: 100%; text-align: center; display: flex; text-align: center; justify-content: center;align-items: center;">

            {{ float_to_percentage(getScopeData(scope.row, item.key, item)) }}
          </div>

          <div v-else-if="item.type == 'list_show'" style="width: 100%; height: 100%; text-align: center; display: flex; text-align: center; justify-content: space-evenly;align-items: center;
          ">
            <!-- 嵌套子表格，主逻辑类似于大表格，但是子表格不能再嵌套子表格 且目前只支持text数据，支持操作btn, 为span, 可以通过style 设置样式 -->
            <el-table :data="getScopeData(scope.row, item.key, item)" style="width: 100%" row-key="id"
              :header-row-style="{ height: '15px !important', fontSize: '12px !important', textAlign: 'center' }"
              :row-style="{ height: '10px !important', fontSize: '12px !important' }"
              :header-cell-style="{ textAlign: 'center', lineHeight: '30px !important', padding: '0px !important', fontSize: '12px !important' }"
              :cell-style="{ textAlign: 'center', lineHeight: '20px !important', padding: '0px !important', fontSize: '12px !important' }"
              :size="mini" border lazy :load="load">

              <el-table-column v-for="child_table_item in item.column" :prop="child_table_item.key"
                :label="child_table_item.label" :parent-row="scope.row" :key="child_table_item.key"
                :width="child_table_item.minWidth ? child_table_item.minWidth : 40">
                <template slot-scope="childScope">
                  <div
                    :style="child_table_item.clickEvent ? `cursor: pointer;${child_table_item.style ? child_table_item.style : ''}` : ''"
                    @click="clickEvent(child_table_item, childScope.row)">{{ getScopeData(childScope.row,
                      child_table_item.key, child_table_item) }}</div>
                </template>
              </el-table-column>

              <el-table-column label="操作" :min-width="item.btn.length * 40" align="center"
                v-if="item.btn && item.btn.length !== 0">
                <template slot-scope="childScope">
                  <span style="cursor: pointer;" :style="item.style" size="mini"
                    @click="dialogEvent(childScope.$index, childScope.row, item, scope.row)"
                    v-for="(item, index) in item.btn" :key="index"
                    v-show="item.showVerfiy ? showVerfiy(item, childScope) : true">{{
                      item.label }}</span>
                  <!-- <el-button size="mini" type="danger" @click="deleteUser(scope.$index, scope.row)">删除</el-button>
                <el-button size="mini" type="success" @click="resetpwd(scope.$index, scope.row)">重置密码</el-button> -->
                </template>
              </el-table-column>

            </el-table>


          </div>

          <div v-else @click="clickEvent(item, scope.row)"
            :style="item.clickEvent ? `cursor: pointer;${item.style ? item.style : ''}` : ''">
            <span v-if="item.before" :style="item.before.style" @click="clickEvent(item.before, scope.row)">
              {{ item.before.text(scope.row) }}
            </span>
            {{ item.calc_column ? item.calc_column(scope.row, getScopeData(scope.row, item.key,
              item)) : getScopeData(scope.row,
                item.key, item) }}
            <span v-if="item.after" :style="item.after.style" @click="clickEvent(item.after, scope.row)">
              {{ item.after.text(scope.row) }}
            </span>
          </div>
        </template>
      </el-table-column>

      <!-- <el-table-column align="center" sortable prop="userMobile" label="手机号"> </el-table-column>
    <el-table-column align="center" sortable prop="userEmail" label="邮件"> </el-table-column>
    <el-table-column align="center" sortable prop="editTime" label="注册时间">
      <template slot-scope="scope">
        
      </template>
    </el-table-column>
    <el-table-column align="center" sortable prop="roleId" label="权限">
      <template slot-scope="scope">
        <div>{{ scope.row.roleId ? '系统管理员' : '普通用户' }}</div>
      </template>
    </el-table-column> -->

      <el-table-column label="操作" :min-width="tableColumn.btn.length * 80" align="center"
        v-if="tableColumn.btn && tableColumn.btn.length !== 0">
        <template slot-scope="scope">
          <el-button :type="item.style" size="mini" @click="dialogEvent(scope.$index, scope.row, item)"
            v-for="(item, index) in tableColumn.btn" :key="index"
            v-show="item.showVerfiy ? showVerfiy(item, scope) : true">{{
              item.label }}</el-button>
          <!-- <el-button size="mini" type="danger" @click="deleteUser(scope.$index, scope.row)">删除</el-button>
        <el-button size="mini" type="success" @click="resetpwd(scope.$index, scope.row)">重置密码</el-button> -->
        </template>
      </el-table-column>
    </el-table>
    <el-col style="height: 50px; display: flex; justify-content: start; align-items: end" v-if="use_paginate">
      <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="currentPage"
        :page-sizes="[20, 50, 100, 200]" :page-size="pageSize" layout="total, sizes, prev, pager, next, jumper"
        :total="myPaginate.total"> </el-pagination>
    </el-col>
  </div>
</template>

<script>

export default {
  name: 'cTable',
  data() {
    return {
      currentPage: 1,
      pageSize: 20,
      myTableData: [],
      myPaginate: [],
      multipleSelection: []
    }
  },
  mounted() { },
  watch: {
    // tableData() {
    //   this.myTableData = this.tableData
    //   console.log('myTableData', this.myTableData)

    // },

    tableData: {
      handler(newVal) {
        
        // 提前处理不在row中的showChoose中的字段, 并写入row
        this.myTableData = newVal;
        if (this.tableColumn?.column?.length > 0) {
          for (let item of this.tableColumn.column) {
            if (item.showChoose) {
              for (let obj of this.myTableData) {
                if (item.showChoose.split('.').reduce((o, k) => o?.[k], obj)) {
                  let res = item.showChoose.split('.').reduce((o, k) => o?.[k], obj)
                  if (item.calc_column) {
                    this.$set(obj, item.key, item.calc_column(obj, res))
                  }
                  else {
                    this.$set(obj, item.key, res)
                  }
                }
              }
            }
          }
        }
      },
      immediate: true
    },

    tableColumn: {
      handler(newVal) {
        this.tableColumn = newVal;
      },
      immediate: true
    },
    paginate() {
      this.myPaginate = this.paginate
      this.currentPage = this.paginate.current
      this.pageSize = this.paginate.size
    }
  },
  methods: {

    // clickEvent 用于内嵌table_column 的点击事件，可以在config.js 中自己回调处理也可以使用该table 操作栏的btn来触发，
    // 使用了use_tablebtn_event 那clickEvent 的回调就会失效 use_tablebtn_event 可以看作是一个自定义的table_btn, 等价于原本就在操作栏的btn,
    // 同样也需要要传递相同的参数。
    clickEvent(item, row) {
      if (item.use_tablebtn_event) {
        this.dialogEvent(0, row, item.use_tablebtn_event)
      }
      else if (item.clickEvent) {
        item.clickEvent(row)
      }
    },
    // 不知道为什么row 一直是空的，但是打印 可以拿到, 先不管这个了
    // tableRowClassName({row, rowIndex}) {       
    //   },
    get_row_many(map_index, item, value) {

      let res_data = []
      let temp_data = []
      if (map_index == 0 && !Array.isArray(item.map[0])) {
        temp_data = item.map
      }
      else {
        temp_data = item.map[map_index]
      }

      for (let i of temp_data) {
        if (i.calc_show) {
          if (i.calc_show(value)) {
            res_data.push(
              { "label": i.label, "value": value[i.key], "style": i.style }
            )
          }
        }
        else {
          res_data.push(
            { "label": i.label, "value": value[i.key], "style": i.style }
          )
        }

      }
      return res_data

    },

    // getScopeData 深度获取对象值, 解决之前'a.b.c.d'获取不到的情况,  2024版本新增
    getScopeData(obj, path, item) {

      // showChoose 允许使用一个新的key代替原来的占位数据, 并且让这个key的值是占位数据
      // @example 在后端返回的数据里有一个key是order_id, 但是现在需要额外备份这个数据,可以使用新的变量order_code 来代替, 值是原来order_id的值,
      // 如果改字段使用了calc_column 则新的key的值会是calc_column的返回值, 即最终展示的数据
        return path.split('.').reduce((o, k) => o?.[k], obj)
    },



    /**
     * 将浮点数转换为百分数
     * @param {Number} num - 需要转换的浮点数或浮点字符串
     * @param {Number} [fixed=2] - 小数点后保留的位数
     * @param {Number} [multiply=1] - 需要乘以的数字
     * @return {String} 百分数
     */
    float_to_percentage(num, fixed = 2, multiply = 100) {
      if (typeof num == 'string') {
        num = parseFloat(num)
      }
      num = num * multiply
      return (num).toFixed(fixed) + '%';
    },






    // 对button 进行验证, 2024.5.20版本新增
    showVerfiy(item, scope) {
      if (item.showVerfiy.func) {
        // 函数验证'
        return item.showVerfiy.func()
      }
      else {
        if (scope.row[item.showVerfiy.key] == item.showVerfiy.value) {
          return true
        }
      }
    },
    handleSelectionChange(val) {
      this.multipleSelection = val;
    },
    mapName(item, value) {
      if (item.multiple) {
        let res = []
        for (const iterator of value) {
          let data = item.data.find(t => t.value == iterator)
          if (data) {
            res.push(data.name)
          }
        }
        return res
      }
      else {
        for (const iterator of item.data) {
          if (iterator.value == value) return [iterator.name]
        }
      }
    },
    /**
     * @description: table btn 的点击事件，会emit 一个 dialogEvent 事件, 传递的参数是 true, item, row
     * @param {Number} index btn 在table btn 中的索引
     * @param {Object} row  table 中的行数据
     * @param {Object} item  table btn 的配置
     * @param {Object} parent_row  table btn 的父级行数据,用于传递参数给内嵌表格
     */
    dialogEvent(index, row, item, parent_row = null) {
      if (parent_row) {

        // 操作内嵌表格时可能需要外部表格的数据传参到子表格，需要再config.js js 中设置parent_row_map_to_row:[{parent:key, child:key}]
        if (item.parent_row_map_to_row) {
          for (const iterator of item.parent_row_map_to_row) {
            row[iterator.children] = parent_row[iterator.parent]
          }
        }
      }
      this.$emit('dialogEvent', true, item, row)
    },
    handleSizeChange(t1) {
      this.pageSize = t1
      this.searchEvent()
    },
    handleCurrentChange(t1) {
      this.currentPage = t1
      this.searchEvent()
    },
    searchEvent() {
      this.$emit('searchEvent', true)
    }
  },
  props: {
    tableColumn: {
      type: Object,
      required: true
    },
    tableData: {
      type: Array,
      required: true
    },
    paginate: {
      require: true
    },
    use_paginate: {
      type: Boolean,
      default: true
    },
    tableHeight: {
      type: String,
      default: null
    }
  }
}
</script>

<style lang="css" scoped></style>
